1 Report

1.1 Research question

Can a trend in the geographical spread of Swedish Viking runestones be observed by comparing the proportion of runestones with and without crosses over time?

This report ascertains associative trends between the establishment of runestones in the Gotland region and the concurrent Christianisation in Gotland and Uppsala counties with analysis to assess the scope of this model for further predictions.

1.2 Executive Summary

Analysis of categorical data (crosses/time period) revealed that Uppsala and Gotland runestones were predominantly erected between 1050-1100 AD. Majority of Uppsala’s crosses are observed during this period, however, none of the analysed runestones from Gotland featured the cross motif. This elucidates the non-uniform, nuanced spread of Christianity across Sweden.

1.3 Initial Data Analysis

Reliant upon visual interpretation, the data is subject to observation bias. Confounders including time and environment contribute to bias by making certain stylistic features across different rune-carvers indistinguishable. Data integrity and reliability is compromised by using multiple data sources and interpretation based on secondary archaeological sources including the epic Beowulf.

Selection bias occurred as ambiguous data including question marks, multiple categorisations, and unclassified data was re-categorised into 8 categories: RAK, Fp, Pr1-5 and NA. This report’s graphical summaries compound selection bias by only focusing on Uppsala and Gotland municipalities. By omitting large quantities of data, the results cannot characterise Viking society broadly as macroscopic trends may be unclear or skewed. Further, by narrowing our range of analysis to two municipalities, we cannot extrapolate trends to other regions. Similar case by case analysis must be conducted to construct plausible predictions for alternative locations. Additionally, runestones with overlapping time periods were only recognised in this report by the earliest of their assigned periods, causing categorical bias. Likewise, runestones which lacked a cross/no cross classification were grouped with those having no cross.

While it is noted that bias hinders the plausibility of conclusions drawn, this is largely inherent to archaeological studies.

1.4 Research overview

Limited to Svealand, Christian influences from missionaries commenced in 830 AD, catalysing an evolution of the location and design of runestones. Rising political tension with neighbouring Christian areas induced Christianisation, thus, the prospect of superior trade and economic performance propelled conversion rather than the pursuit of holiness.

Uppsala observes an influx of runestone prevalence during 1060-1100 AD (Pr4), concurrent with the increase of runestone crosses. Its close proximity to the Baltic Sea on the south-east coast of modern day Sweden, facilitated the introduction of foriegn social and religious influences to the Vikings. This supported a transition from polytheistic paganism towards monotheistic Christianity over the short period revealed by the surge in runestone crosses. This period followed the first Christian evangelisation mission in Uppsala, led by Saint Ansgar during the 9th century, providing context to this stage of religious conversion.

From the classified runestones in Gotland, a significant proportion were erected during the Pr4 period. Unlike Uppsala, no crosses were observed on runestones across all time periods. This not only suggests an uneven spread of Christian beliefs throughout Viking society, but also the need for models alike to identify subtle trends in data. Gotland is isolated from mainland Sweden and therefore bound to undergo religious transformation after other municipalities like Uppsala, which was well-connected with multiple regions and foreign influences via trade interactions. Findings from the maps are supported by churches’ locations in these municipalities. Nonetheless, archaeologists currently lack evidence to determine whether runestones were erected at churches, subsequent church sites, or brought to churches later.

Grouped bar plots quantified the comparison of runestones with/without crosses. While a larger quantity of runestones is observed in Uppsala, the most notable trend was the complete absence of crosses on runestones in Gotland. This may be attributed to the vast majority of runestones in Gotland lacking cross identification, thus classed in this report as ‘no cross’. This assumption may be misleading.

Hence, Christianization of the Vikings began in well-connected municipalities, susceptible to foriegn influences. Christianity slowly infiltrated more regional and often isolated municipalities, however, conversion was not observed as heavily in these regions.


2 Mapping the geographical spread across municipalities

2.1 Loading library packages

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ ggplot2 3.3.5     ✓ purrr   0.3.4
## ✓ tibble  3.1.6     ✓ dplyr   1.0.8
## ✓ tidyr   1.2.0     ✓ stringr 1.4.0
## ✓ readr   2.1.2     ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(ggplot2)
library(readxl)
library(maps)
## 
## Attaching package: 'maps'
## The following object is masked from 'package:purrr':
## 
##     map
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(ggthemes)
library(ggmap)
## Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
## Please cite ggmap if you use it! See citation("ggmap") for details.
## 
## Attaching package: 'ggmap'
## The following object is masked from 'package:plotly':
## 
##     wind
library(wesanderson)
library(RColorBrewer)

2.2 Preliminary Analysis of runestones in different municipalities

Arch <- read_xls("Arch_main.xls")

Arch = mutate(Arch,ClassNew = case_when(
  grepl('RAK',Classification)~'RAK',
  grepl('Fp',Classification)~'Fp',
  grepl('Pr1',Classification)~'Pr1',
  grepl('Pr2',Classification)~'Pr2',
  grepl('Pr3',Classification)~'Pr3',
  grepl('Pr4',Classification)~'Pr4',
  grepl('Pr5',Classification)~'Pr5',
  TRUE~ 'NA'
))

table(Arch$ClassNew)
## 
##   Fp   NA  Pr1  Pr2  Pr3  Pr4  Pr5  RAK 
##  212 2308   90  205  303  427   62  561
Arch$ClassNew <- factor(Arch$ClassNew,levels=c("RAK","Fp","Pr1","Pr2","Pr3","Pr4","Pr5","NA"), ordered=TRUE)

ggplot(data=Arch,aes(x=ClassNew))+geom_bar(fill="light blue")+
  ggtitle("Runestone Typology across different Time Periods in Sweden")+
  labs(x="Time Periods",y="Number of Runestones") + 
  theme_clean()

2.3 Importing data

rune_mast <- read_xlsx("Uppsala_trial.xlsx")
as.data.frame(rune_mast)
runedata <- read_xlsx("1Gotlandclean.xlsx")
as.data.frame(runedata) 

2.3.1 Summary of data sets

summary(rune_mast)
##       ID                Cross           Place              Socken         
##  Length:305         Min.   :0.0000   Length:305         Length:305        
##  Class :character   1st Qu.:0.0000   Class :character   Class :character  
##  Mode  :character   Median :0.0000   Mode  :character   Mode  :character  
##                     Mean   :0.3115                                        
##                     3rd Qu.:1.0000                                        
##                     Max.   :1.0000                                        
##     Härad              Kommun          Classification        Latitude    
##  Length:305         Length:305         Length:305         Min.   :58.39  
##  Class :character   Class :character   Class :character   1st Qu.:59.86  
##  Mode  :character   Mode  :character   Mode  :character   Median :59.88  
##                                                           Mean   :59.88  
##                                                           3rd Qu.:59.95  
##                                                           Max.   :60.16  
##       Long           Longitude          Lat         
##  Min.   :6625825   Min.   :13.58   Min.   :1582025  
##  1st Qu.:6638510   1st Qu.:17.51   1st Qu.:1595827  
##  Median :6642537   Median :17.62   Median :1600608  
##  Mean   :6644023   Mean   :17.55   Mean   :1600726  
##  3rd Qu.:6649850   3rd Qu.:17.69   3rd Qu.:1604533  
##  Max.   :6671945   Max.   :18.68   Max.   :1643937
summary(runedata)
##     Signum            Crosses             Plats              Socken         
##  Length:267         Length:267         Length:267         Length:267        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##     Härad              Kommun            Classif            Ristare         
##  Length:267         Length:267         Length:267         Length:267        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  Materialtyp          Bildlänk              Lat             Long      
##  Length:267         Length:267         Min.   :56.94   Min.   :18.09  
##  Class :character   Class :character   1st Qu.:57.27   1st Qu.:18.30  
##  Mode  :character   Mode  :character   Median :57.49   Median :18.47  
##                                        Mean   :57.47   Mean   :18.50  
##                                        3rd Qu.:57.71   3rd Qu.:18.70  
##                                        Max.   :57.92   Max.   :19.10

2.3.2 Data Cleaning

rune_mast = mutate(rune_mast,classif = case_when(
  grepl('RAK',Classification)~'RAK',
  grepl('Fp',Classification)~'Fp',
  grepl('Pr1',Classification)~'Pr1',
  grepl('Pr2',Classification)~'Pr2',
  grepl('Pr3',Classification)~'Pr3',
  grepl('Pr4',Classification)~'Pr4',
  grepl('Pr5',Classification)~'Pr5',
  TRUE~ 'NA'))

data = mutate(runedata,Classif = case_when(
  grepl('RAK',Classif)~'RAK',
  grepl('Fp',Classif)~'Fp',
  grepl('Pr1',Classif)~'Pr1',
  grepl('Pr2',Classif)~'Pr2',
  grepl('Pr3',Classif)~'Pr3',
  grepl('Pr4',Classif)~'Pr4',
  grepl('Pr5',Classif)~'Pr5',
  TRUE~ 'NA'))

runedata$Classif <- factor(runedata$Classif, levels = c("RAK","Fp","Pr1","Pr2","Pr3","Pr4","Pr5","NA"), ordered = TRUE)

rune_mast$classif <- factor(rune_mast$classif, levels = c("RAK","Fp","Pr1","Pr2","Pr3","Pr4","Pr5","NA"), ordered = TRUE)

2.4 Uppsala county

Maps

Class <- rune_mast$classif
Crosses <- factor(rune_mast$Cross, levels = c(0:1))
uppsala_map <- get_stamenmap(bbox =c(16.9794,59.6788,18.5751,60.1381), maptype="toner-lite",
  zoom=11)
## 60 tiles needed, this may take a while (try a smaller zoom).
## Source : http://tile.stamen.com/toner-lite/11/1120/593.png
## Source : http://tile.stamen.com/toner-lite/11/1121/593.png
## Source : http://tile.stamen.com/toner-lite/11/1122/593.png
## Source : http://tile.stamen.com/toner-lite/11/1123/593.png
## Source : http://tile.stamen.com/toner-lite/11/1124/593.png
## Source : http://tile.stamen.com/toner-lite/11/1125/593.png
## Source : http://tile.stamen.com/toner-lite/11/1126/593.png
## Source : http://tile.stamen.com/toner-lite/11/1127/593.png
## Source : http://tile.stamen.com/toner-lite/11/1128/593.png
## Source : http://tile.stamen.com/toner-lite/11/1129/593.png
## Source : http://tile.stamen.com/toner-lite/11/1120/594.png
## Source : http://tile.stamen.com/toner-lite/11/1121/594.png
## Source : http://tile.stamen.com/toner-lite/11/1122/594.png
## Source : http://tile.stamen.com/toner-lite/11/1123/594.png
## Source : http://tile.stamen.com/toner-lite/11/1124/594.png
## Source : http://tile.stamen.com/toner-lite/11/1125/594.png
## Source : http://tile.stamen.com/toner-lite/11/1126/594.png
## Source : http://tile.stamen.com/toner-lite/11/1127/594.png
## Source : http://tile.stamen.com/toner-lite/11/1128/594.png
## Source : http://tile.stamen.com/toner-lite/11/1129/594.png
## Source : http://tile.stamen.com/toner-lite/11/1120/595.png
## Source : http://tile.stamen.com/toner-lite/11/1121/595.png
## Source : http://tile.stamen.com/toner-lite/11/1122/595.png
## Source : http://tile.stamen.com/toner-lite/11/1123/595.png
## Source : http://tile.stamen.com/toner-lite/11/1124/595.png
## Source : http://tile.stamen.com/toner-lite/11/1125/595.png
## Source : http://tile.stamen.com/toner-lite/11/1126/595.png
## Source : http://tile.stamen.com/toner-lite/11/1127/595.png
## Source : http://tile.stamen.com/toner-lite/11/1128/595.png
## Source : http://tile.stamen.com/toner-lite/11/1129/595.png
## Source : http://tile.stamen.com/toner-lite/11/1120/596.png
## Source : http://tile.stamen.com/toner-lite/11/1121/596.png
## Source : http://tile.stamen.com/toner-lite/11/1122/596.png
## Source : http://tile.stamen.com/toner-lite/11/1123/596.png
## Source : http://tile.stamen.com/toner-lite/11/1124/596.png
## Source : http://tile.stamen.com/toner-lite/11/1125/596.png
## Source : http://tile.stamen.com/toner-lite/11/1126/596.png
## Source : http://tile.stamen.com/toner-lite/11/1127/596.png
## Source : http://tile.stamen.com/toner-lite/11/1128/596.png
## Source : http://tile.stamen.com/toner-lite/11/1129/596.png
## Source : http://tile.stamen.com/toner-lite/11/1120/597.png
## Source : http://tile.stamen.com/toner-lite/11/1121/597.png
## Source : http://tile.stamen.com/toner-lite/11/1122/597.png
## Source : http://tile.stamen.com/toner-lite/11/1123/597.png
## Source : http://tile.stamen.com/toner-lite/11/1124/597.png
## Source : http://tile.stamen.com/toner-lite/11/1125/597.png
## Source : http://tile.stamen.com/toner-lite/11/1126/597.png
## Source : http://tile.stamen.com/toner-lite/11/1127/597.png
## Source : http://tile.stamen.com/toner-lite/11/1128/597.png
## Source : http://tile.stamen.com/toner-lite/11/1129/597.png
## Source : http://tile.stamen.com/toner-lite/11/1120/598.png
## Source : http://tile.stamen.com/toner-lite/11/1121/598.png
## Source : http://tile.stamen.com/toner-lite/11/1122/598.png
## Source : http://tile.stamen.com/toner-lite/11/1123/598.png
## Source : http://tile.stamen.com/toner-lite/11/1124/598.png
## Source : http://tile.stamen.com/toner-lite/11/1125/598.png
## Source : http://tile.stamen.com/toner-lite/11/1126/598.png
## Source : http://tile.stamen.com/toner-lite/11/1127/598.png
## Source : http://tile.stamen.com/toner-lite/11/1128/598.png
## Source : http://tile.stamen.com/toner-lite/11/1129/598.png
ggmap(uppsala_map)+
  geom_point(
  data = rune_mast, 
  aes(x=Longitude, y=Latitude, color=Class, shape=Crosses),size=2.5, alpha=0.4)+
  theme_map()+theme(legend.background = element_blank(), legend.position = "bottom")+
  guides(fill=guide_legend(title="Classification"))+
  ggtitle("Geographical distribution of Runestones in the Uppsala County")

ggmap(uppsala_map)+
  geom_point(
  data = rune_mast, 
  aes(x=Longitude, y=Latitude, col=Crosses),size=2, alpha=0.4)+
  theme_map()+
  theme(legend.background = element_blank(), legend.position = "bottom")+
  guides(fill=guide_legend(title="Classification"))+
  ggtitle("Geographical distribution of Runestones in the Uppsala County")+
  facet_wrap(vars(classif))+
  theme(legend.background = element_blank(), legend.position = "right")+
  scale_color_manual(values=wes_palette(n=3, name="BottleRocket1"))

Number of Crosses over time

uppsala_cross <- ggplot(data = rune_mast, aes(x = Class))+
  geom_bar(aes(fill=Crosses), position = "dodge")+
  ggtitle("Proportion of Crosses across Time in Uppsala")+
  theme(legend.background = element_blank(), legend.position = "bottom")+ 
  theme_bw()
  
ggplotly(uppsala_cross)

2.5 Gotland County

Maps

Classes <- runedata$Classif
gotland_map <- get_stamenmap(
  bbox = c(left = 17.5, bottom = 57.0, right = 19.8, top = 57.9),
  maptype = "toner-lite",
  zoom = 9
)
## Source : http://tile.stamen.com/toner-lite/9/280/154.png
## Source : http://tile.stamen.com/toner-lite/9/281/154.png
## Source : http://tile.stamen.com/toner-lite/9/282/154.png
## Source : http://tile.stamen.com/toner-lite/9/283/154.png
## Source : http://tile.stamen.com/toner-lite/9/284/154.png
## Source : http://tile.stamen.com/toner-lite/9/280/155.png
## Source : http://tile.stamen.com/toner-lite/9/281/155.png
## Source : http://tile.stamen.com/toner-lite/9/282/155.png
## Source : http://tile.stamen.com/toner-lite/9/283/155.png
## Source : http://tile.stamen.com/toner-lite/9/284/155.png
## Source : http://tile.stamen.com/toner-lite/9/280/156.png
## Source : http://tile.stamen.com/toner-lite/9/281/156.png
## Source : http://tile.stamen.com/toner-lite/9/282/156.png
## Source : http://tile.stamen.com/toner-lite/9/283/156.png
## Source : http://tile.stamen.com/toner-lite/9/284/156.png
ggmap(gotland_map) +
  geom_point(data = runedata,
             aes(x = Long, y = Lat,col = Classif), 
             size = 2, alpha = 0.7) +
  labs(title = "Overall Distribution of Runestones in the Gotland County") +
  theme_map() +
  theme(legend.background = element_blank(), legend.position = "bottom")

ggmap(gotland_map) +
  geom_point(data = runedata,
             aes(x = Long, y = Lat, fill=Crosses),alpha = 0.5,
             size = 0.9, col = "red") + facet_wrap(vars(Classif))+
 ggtitle("Geographical Distribution of Runestones in the Gotland County") +
  theme_map() +
  theme(legend.background = element_blank(), legend.position = "bottom") 

Number of crosses over time

Crosses.Gotland <- runedata$Crosses
gotland_cross <- ggplot(data = runedata, aes(x = Classes))+geom_bar(aes(fill=Crosses.Gotland))+ 
  theme(legend.background = element_blank(), legend.position = "bottom")+
  ggtitle("Proportion of Crosses across Time in Gotland")+ theme_bw()


ggplotly(gotland_cross)

3 Acknowledgements

Role Coordinator Support
Presentation Ariel, Jacqui (presenter) Luana
Coding Shradha Ru
Scheduling Luana
Research Jennifer Ariel, Luana (editors)

Meetings

Date, time Presentee(s) Discussion points
8/3 (11am-12pm) All Possible research questions; Finalise roles
15/3 (11am-12pm) All Finalise research question
22/3 (11am-12pm) All Conduct domain research and consolidate findings with group members
29/3 (11am-12pm) All Discuss approach of research question; Begin report draft; Begin coding for graphical summaries
5/4 (11am-12pm) All Finalise graphical summaries; Derive trends from graphical summaries
12/4 (11am-12pm) All Film presentation; Finalise report

4 Articles for further reading

Knutson, S. A. (2016). Bridges to Eternity: A Re-Examination of the Adoption of Christianity in Viking-Age Sweden. Viking and Medieval Scandinavia, 12, 87–102. https://www.jstor.org/stable/48501798

Knuston asserts that Christianity was actively uptaken by the Vikings, particularly in well-connected municipalities which benefited from access to foreign influences via trade interactions.

Thoeming, A. (2016). Dealing with Data: Naïve Bayesian Classification and a Case Study from Viking Age Sweden. International Journal of Student Research in Archaeology, 1(1), 193-204. https://www.academia.edu/21431922/Dealing_with_Data_Na%C3%AFve_Bayesian_Classification_and_a_case_study_from_Viking_Age_Sweden

Encountering similar limitations in the data to this report, Thoeming determined that the Bayesian classifier was limited, only providing broader categorisations in feature combinations and differences.

5 References

Tutorial for creating maps: https://www.youtube.com/watch?v=2k8O-Y_uiRU

Conversion of coordinates: https://coordinates-converter.com/en/decimal/51.000000,10.000000?karte=OpenStreetMap&zoom=8

Data Cleaning: Freya and Sean (Tuesday Lab CC)

LS0tCnRpdGxlOiAiREFUQSAxOTAxIFByb2plY3QgMiIKYXV0aG9yOiAiKlNocmFkaGEgSXllciAoc2l5ZTcwMDcpLCBSdSBZdW4gTGl1IChybGl1MDAyNiksIEphY3F1ZWxpbmUgTGFpIChqbGFpMjk4MCksIEx1YW5hIFJlbmRpbmEgKGxyZW44NzQ2KSwgQXJpZWwgQ3phamtvd3NraSAoYWN6YTI4ODgpLCBKZW5uaWZlciBTdW4gKGpzdW41MDI0KSoiCmRhdGU6ICJTZW1lc3RlciAxLCAyMDIyIHwgVW5pdmVyc2l0eSBvZiBTeWRuZXkiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZSAjIGVtYmVkIC5SbWQgZmlsZQogICAgdG9jOiB0cnVlICAjIHRhYmxlIG9mIGNvbnRlbnRzCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogdHJ1ZSAjIHRvYyBpcyBhbHdheXMgdmlzaWJsZSB3aGVuIHNjcm9sbGVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUgCiAgICB0aGVtZTogbHVtZW4gIyB0aGVtZSB0aGUgZG9jCiAgICBoaWdobGlnaHQ6IHRhbmdvICMgdGhlbWUgc3ludGF4IGNvbG91cmluZwogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKYGBge2NzcyBuZXdzdHlsZXMsIGVjaG89RkFMU0V9CmgxLCAuaDEsIGgyLCAuaDIsIGgzLCAuaDMgeyAvKiBBZGQgc3BhY2UgYmVmb3JlIGhlYWRpbmdzOiAqLwogICAgbWFyZ2luLXRvcDogNTZweDsKfQpoMSwgaDIgeyAvKiBhZGQgYm9yZGVyIHRvIGgxIGFuZCBoMiAqLwogIGJvcmRlci1ib3R0b206IHNvbGlkIDFweCAjNjY2Owp9CmgyIHsgLyogUmVzaXplIGhlYWRlciAyOiAqLwogIGZvbnQtc2l6ZTogMjJweDsKfQpib2R5IHsgLyogTWFrZSBtYWluIHRleHQgY29sb3VyIGJsYWNrICovCiAgY29sb3I6IGJsYWNrOwp9CmEgeyAvKiBMaW5rIGNvbG91cnMgKi8KICBjb2xvcjogYmx1ZTsKfQoudG9jaWZ5IHsgLyogU29tZSB0b2MgZml4ZXMqLwogIHdpZHRoOiAxMDAlICFpbXBvcnRhbnQ7CiAgYm9yZGVyOiBub25lOyAvKiByZW1vdmUgYm9yZGVyICovCn0KLnRvY2lmeS1oZWFkZXIgeyAvKiBmaXggZm9yIGhvcnJpYmxlIGluZGVudCBpbiB0b2MgKi8KICB0ZXh0LWluZGVudDogaW5pdGlhbDsKfQoKYGBgCgojIFJlcG9ydCAKCiMjIFJlc2VhcmNoIHF1ZXN0aW9uCgpDYW4gYSB0cmVuZCBpbiB0aGUgZ2VvZ3JhcGhpY2FsIHNwcmVhZCBvZiBTd2VkaXNoIFZpa2luZyBydW5lc3RvbmVzIGJlIG9ic2VydmVkIGJ5IGNvbXBhcmluZyB0aGUgcHJvcG9ydGlvbiBvZiBydW5lc3RvbmVzIHdpdGggYW5kIHdpdGhvdXQgY3Jvc3NlcyBvdmVyIHRpbWU/IAoKVGhpcyByZXBvcnQgYXNjZXJ0YWlucyBhc3NvY2lhdGl2ZSB0cmVuZHMgYmV0d2VlbiB0aGUgZXN0YWJsaXNobWVudCBvZiBydW5lc3RvbmVzIGluIHRoZSBHb3RsYW5kIHJlZ2lvbiBhbmQgdGhlIGNvbmN1cnJlbnQgQ2hyaXN0aWFuaXNhdGlvbiBpbiBHb3RsYW5kIGFuZCBVcHBzYWxhIGNvdW50aWVzIHdpdGggYW5hbHlzaXMgdG8gYXNzZXNzIHRoZSBzY29wZSBvZiB0aGlzIG1vZGVsIGZvciBmdXJ0aGVyIHByZWRpY3Rpb25zLgoKCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5CgpBbmFseXNpcyBvZiBjYXRlZ29yaWNhbCBkYXRhIChjcm9zc2VzL3RpbWUgcGVyaW9kKSByZXZlYWxlZCB0aGF0IFVwcHNhbGEgYW5kIEdvdGxhbmQgcnVuZXN0b25lcyB3ZXJlIHByZWRvbWluYW50bHkgZXJlY3RlZCBiZXR3ZWVuIDEwNTAtMTEwMCBBRC4gTWFqb3JpdHkgb2YgVXBwc2FsYeKAmXMgY3Jvc3NlcyBhcmUgb2JzZXJ2ZWQgZHVyaW5nIHRoaXMgcGVyaW9kLCBob3dldmVyLCBub25lIG9mIHRoZSBhbmFseXNlZCBydW5lc3RvbmVzIGZyb20gR290bGFuZCBmZWF0dXJlZCB0aGUgY3Jvc3MgbW90aWYuIFRoaXMgZWx1Y2lkYXRlcyB0aGUgbm9uLXVuaWZvcm0sIG51YW5jZWQgc3ByZWFkIG9mIENocmlzdGlhbml0eSBhY3Jvc3MgU3dlZGVuLgoKCiMjIEluaXRpYWwgRGF0YSBBbmFseXNpcwoKUmVsaWFudCB1cG9uIHZpc3VhbCBpbnRlcnByZXRhdGlvbiwgdGhlIGRhdGEgaXMgc3ViamVjdCB0byBvYnNlcnZhdGlvbiBiaWFzLiBDb25mb3VuZGVycyBpbmNsdWRpbmcgdGltZSBhbmQgZW52aXJvbm1lbnQgY29udHJpYnV0ZSB0byBiaWFzIGJ5IG1ha2luZyBjZXJ0YWluIHN0eWxpc3RpYyBmZWF0dXJlcyBhY3Jvc3MgZGlmZmVyZW50IHJ1bmUtY2FydmVycyBpbmRpc3Rpbmd1aXNoYWJsZS4gRGF0YSBpbnRlZ3JpdHkgYW5kIHJlbGlhYmlsaXR5IGlzIGNvbXByb21pc2VkIGJ5IHVzaW5nIG11bHRpcGxlIGRhdGEgc291cmNlcyBhbmQgaW50ZXJwcmV0YXRpb24gYmFzZWQgb24gc2Vjb25kYXJ5IGFyY2hhZW9sb2dpY2FsIHNvdXJjZXMgaW5jbHVkaW5nIHRoZSBlcGljIEJlb3d1bGYuICAgCgpTZWxlY3Rpb24gYmlhcyBvY2N1cnJlZCBhcyBhbWJpZ3VvdXMgZGF0YSBpbmNsdWRpbmcgcXVlc3Rpb24gbWFya3MsIG11bHRpcGxlIGNhdGVnb3Jpc2F0aW9ucywgYW5kIHVuY2xhc3NpZmllZCBkYXRhIHdhcyByZS1jYXRlZ29yaXNlZCBpbnRvIDggY2F0ZWdvcmllczogUkFLLCBGcCwgUHIxLTUgYW5kIE5BLiBUaGlzIHJlcG9ydOKAmXMgZ3JhcGhpY2FsIHN1bW1hcmllcyBjb21wb3VuZCBzZWxlY3Rpb24gYmlhcyBieSBvbmx5IGZvY3VzaW5nIG9uIFVwcHNhbGEgYW5kIEdvdGxhbmQgbXVuaWNpcGFsaXRpZXMuIEJ5IG9taXR0aW5nIGxhcmdlIHF1YW50aXRpZXMgb2YgZGF0YSwgdGhlIHJlc3VsdHMgY2Fubm90IGNoYXJhY3RlcmlzZSBWaWtpbmcgc29jaWV0eSBicm9hZGx5IGFzIG1hY3Jvc2NvcGljIHRyZW5kcyBtYXkgYmUgdW5jbGVhciBvciBza2V3ZWQuIEZ1cnRoZXIsIGJ5IG5hcnJvd2luZyBvdXIgcmFuZ2Ugb2YgYW5hbHlzaXMgdG8gdHdvIG11bmljaXBhbGl0aWVzLCB3ZSBjYW5ub3QgZXh0cmFwb2xhdGUgdHJlbmRzIHRvIG90aGVyIHJlZ2lvbnMuIFNpbWlsYXIgY2FzZSBieSBjYXNlIGFuYWx5c2lzIG11c3QgYmUgY29uZHVjdGVkIHRvIGNvbnN0cnVjdCBwbGF1c2libGUgcHJlZGljdGlvbnMgZm9yIGFsdGVybmF0aXZlIGxvY2F0aW9ucy4gQWRkaXRpb25hbGx5LCBydW5lc3RvbmVzIHdpdGggb3ZlcmxhcHBpbmcgdGltZSBwZXJpb2RzIHdlcmUgb25seSByZWNvZ25pc2VkIGluIHRoaXMgcmVwb3J0IGJ5IHRoZSBlYXJsaWVzdCBvZiB0aGVpciBhc3NpZ25lZCBwZXJpb2RzLCBjYXVzaW5nIGNhdGVnb3JpY2FsIGJpYXMuIExpa2V3aXNlLCBydW5lc3RvbmVzIHdoaWNoIGxhY2tlZCBhIGNyb3NzL25vIGNyb3NzIGNsYXNzaWZpY2F0aW9uIHdlcmUgZ3JvdXBlZCB3aXRoIHRob3NlIGhhdmluZyBubyBjcm9zcy4gCgpXaGlsZSBpdCBpcyBub3RlZCB0aGF0IGJpYXMgaGluZGVycyB0aGUgcGxhdXNpYmlsaXR5IG9mIGNvbmNsdXNpb25zIGRyYXduLCB0aGlzIGlzIGxhcmdlbHkgaW5oZXJlbnQgdG8gYXJjaGFlb2xvZ2ljYWwgc3R1ZGllcy4gCgoKIyMgUmVzZWFyY2ggb3ZlcnZpZXcKCkxpbWl0ZWQgdG8gU3ZlYWxhbmQsIENocmlzdGlhbiBpbmZsdWVuY2VzIGZyb20gbWlzc2lvbmFyaWVzIGNvbW1lbmNlZCBpbiA4MzAgQUQsIGNhdGFseXNpbmcgYW4gZXZvbHV0aW9uIG9mIHRoZSBsb2NhdGlvbiBhbmQgZGVzaWduIG9mIHJ1bmVzdG9uZXMuIFJpc2luZyBwb2xpdGljYWwgdGVuc2lvbiB3aXRoIG5laWdoYm91cmluZyBDaHJpc3RpYW4gYXJlYXMgaW5kdWNlZCBDaHJpc3RpYW5pc2F0aW9uLCB0aHVzLCB0aGUgcHJvc3BlY3Qgb2Ygc3VwZXJpb3IgdHJhZGUgYW5kIGVjb25vbWljIHBlcmZvcm1hbmNlIHByb3BlbGxlZCBjb252ZXJzaW9uIHJhdGhlciB0aGFuIHRoZSBwdXJzdWl0IG9mIGhvbGluZXNzLiAKClVwcHNhbGEgb2JzZXJ2ZXMgYW4gaW5mbHV4IG9mIHJ1bmVzdG9uZSBwcmV2YWxlbmNlIGR1cmluZyAxMDYwLTExMDAgQUQgKFByNCksIGNvbmN1cnJlbnQgd2l0aCB0aGUgaW5jcmVhc2Ugb2YgcnVuZXN0b25lIGNyb3NzZXMuIEl0cyBjbG9zZSBwcm94aW1pdHkgdG8gdGhlIEJhbHRpYyBTZWEgb24gdGhlIHNvdXRoLWVhc3QgY29hc3Qgb2YgbW9kZXJuIGRheSBTd2VkZW4sIGZhY2lsaXRhdGVkIHRoZSBpbnRyb2R1Y3Rpb24gb2YgZm9yaWVnbiBzb2NpYWwgYW5kIHJlbGlnaW91cyBpbmZsdWVuY2VzIHRvIHRoZSBWaWtpbmdzLiBUaGlzIHN1cHBvcnRlZCBhIHRyYW5zaXRpb24gZnJvbSBwb2x5dGhlaXN0aWMgcGFnYW5pc20gdG93YXJkcyBtb25vdGhlaXN0aWMgQ2hyaXN0aWFuaXR5IG92ZXIgdGhlIHNob3J0IHBlcmlvZCByZXZlYWxlZCBieSB0aGUgc3VyZ2UgaW4gcnVuZXN0b25lIGNyb3NzZXMuIFRoaXMgcGVyaW9kIGZvbGxvd2VkIHRoZSBmaXJzdCBDaHJpc3RpYW4gZXZhbmdlbGlzYXRpb24gbWlzc2lvbiBpbiBVcHBzYWxhLCBsZWQgYnkgU2FpbnQgQW5zZ2FyIGR1cmluZyB0aGUgOXRoIGNlbnR1cnksIHByb3ZpZGluZyBjb250ZXh0IHRvIHRoaXMgc3RhZ2Ugb2YgcmVsaWdpb3VzIGNvbnZlcnNpb24uIAoKRnJvbSB0aGUgY2xhc3NpZmllZCBydW5lc3RvbmVzIGluIEdvdGxhbmQsIGEgc2lnbmlmaWNhbnQgcHJvcG9ydGlvbiB3ZXJlIGVyZWN0ZWQgZHVyaW5nIHRoZSBQcjQgcGVyaW9kLiBVbmxpa2UgVXBwc2FsYSwgbm8gY3Jvc3NlcyB3ZXJlIG9ic2VydmVkIG9uIHJ1bmVzdG9uZXMgYWNyb3NzIGFsbCB0aW1lIHBlcmlvZHMuIFRoaXMgbm90IG9ubHkgc3VnZ2VzdHMgYW4gdW5ldmVuIHNwcmVhZCBvZiBDaHJpc3RpYW4gYmVsaWVmcyB0aHJvdWdob3V0IFZpa2luZyBzb2NpZXR5LCBidXQgYWxzbyB0aGUgbmVlZCBmb3IgbW9kZWxzIGFsaWtlIHRvIGlkZW50aWZ5IHN1YnRsZSB0cmVuZHMgaW4gZGF0YS4gR290bGFuZCBpcyBpc29sYXRlZCBmcm9tIG1haW5sYW5kIFN3ZWRlbiBhbmQgdGhlcmVmb3JlIGJvdW5kIHRvIHVuZGVyZ28gcmVsaWdpb3VzIHRyYW5zZm9ybWF0aW9uIGFmdGVyIG90aGVyIG11bmljaXBhbGl0aWVzIGxpa2UgVXBwc2FsYSwgd2hpY2ggd2FzIHdlbGwtY29ubmVjdGVkIHdpdGggbXVsdGlwbGUgcmVnaW9ucyBhbmQgZm9yZWlnbiBpbmZsdWVuY2VzIHZpYSB0cmFkZSBpbnRlcmFjdGlvbnMuIEZpbmRpbmdzIGZyb20gdGhlIG1hcHMgYXJlIHN1cHBvcnRlZCBieSBjaHVyY2hlc+KAmSBsb2NhdGlvbnMgaW4gdGhlc2UgbXVuaWNpcGFsaXRpZXMuIE5vbmV0aGVsZXNzLCBhcmNoYWVvbG9naXN0cyBjdXJyZW50bHkgbGFjayBldmlkZW5jZSB0byBkZXRlcm1pbmUgd2hldGhlciBydW5lc3RvbmVzIHdlcmUgZXJlY3RlZCBhdCBjaHVyY2hlcywgc3Vic2VxdWVudCBjaHVyY2ggc2l0ZXMsIG9yIGJyb3VnaHQgdG8gY2h1cmNoZXMgbGF0ZXIuIAoKR3JvdXBlZCBiYXIgcGxvdHMgcXVhbnRpZmllZCB0aGUgY29tcGFyaXNvbiBvZiBydW5lc3RvbmVzIHdpdGgvd2l0aG91dCBjcm9zc2VzLiBXaGlsZSBhIGxhcmdlciBxdWFudGl0eSBvZiBydW5lc3RvbmVzIGlzIG9ic2VydmVkIGluIFVwcHNhbGEsIHRoZSBtb3N0IG5vdGFibGUgdHJlbmQgd2FzIHRoZSBjb21wbGV0ZSBhYnNlbmNlIG9mIGNyb3NzZXMgb24gcnVuZXN0b25lcyBpbiBHb3RsYW5kLiBUaGlzIG1heSBiZSBhdHRyaWJ1dGVkIHRvIHRoZSB2YXN0IG1ham9yaXR5IG9mIHJ1bmVzdG9uZXMgaW4gR290bGFuZCBsYWNraW5nIGNyb3NzIGlkZW50aWZpY2F0aW9uLCB0aHVzIGNsYXNzZWQgaW4gdGhpcyByZXBvcnQgYXMg4oCYbm8gY3Jvc3PigJkuIFRoaXMgYXNzdW1wdGlvbiBtYXkgYmUgbWlzbGVhZGluZy4gIAoKSGVuY2UsIENocmlzdGlhbml6YXRpb24gb2YgdGhlIFZpa2luZ3MgYmVnYW4gaW4gd2VsbC1jb25uZWN0ZWQgbXVuaWNpcGFsaXRpZXMsIHN1c2NlcHRpYmxlIHRvIGZvcmllZ24gaW5mbHVlbmNlcy4gQ2hyaXN0aWFuaXR5IHNsb3dseSBpbmZpbHRyYXRlZCBtb3JlIHJlZ2lvbmFsIGFuZCBvZnRlbiBpc29sYXRlZCBtdW5pY2lwYWxpdGllcywgaG93ZXZlciwgY29udmVyc2lvbiB3YXMgbm90IG9ic2VydmVkIGFzIGhlYXZpbHkgaW4gdGhlc2UgcmVnaW9ucy4gCgoKKioqIAoKIyBNYXBwaW5nIHRoZSBnZW9ncmFwaGljYWwgc3ByZWFkIGFjcm9zcyBtdW5pY2lwYWxpdGllcyAKCiMjIExvYWRpbmcgbGlicmFyeSBwYWNrYWdlcyAKYGBge3IgbGlicmFyeX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkobWFwcykKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoZ2dtYXApCmxpYnJhcnkod2VzYW5kZXJzb24pCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpgYGAKCgojIyBQcmVsaW1pbmFyeSBBbmFseXNpcyBvZiBydW5lc3RvbmVzIGluIGRpZmZlcmVudCBtdW5pY2lwYWxpdGllcwpgYGB7cn0KQXJjaCA8LSByZWFkX3hscygiQXJjaF9tYWluLnhscyIpCgpBcmNoID0gbXV0YXRlKEFyY2gsQ2xhc3NOZXcgPSBjYXNlX3doZW4oCiAgZ3JlcGwoJ1JBSycsQ2xhc3NpZmljYXRpb24pfidSQUsnLAogIGdyZXBsKCdGcCcsQ2xhc3NpZmljYXRpb24pfidGcCcsCiAgZ3JlcGwoJ1ByMScsQ2xhc3NpZmljYXRpb24pfidQcjEnLAogIGdyZXBsKCdQcjInLENsYXNzaWZpY2F0aW9uKX4nUHIyJywKICBncmVwbCgnUHIzJyxDbGFzc2lmaWNhdGlvbil+J1ByMycsCiAgZ3JlcGwoJ1ByNCcsQ2xhc3NpZmljYXRpb24pfidQcjQnLAogIGdyZXBsKCdQcjUnLENsYXNzaWZpY2F0aW9uKX4nUHI1JywKICBUUlVFfiAnTkEnCikpCgp0YWJsZShBcmNoJENsYXNzTmV3KQoKQXJjaCRDbGFzc05ldyA8LSBmYWN0b3IoQXJjaCRDbGFzc05ldyxsZXZlbHM9YygiUkFLIiwiRnAiLCJQcjEiLCJQcjIiLCJQcjMiLCJQcjQiLCJQcjUiLCJOQSIpLCBvcmRlcmVkPVRSVUUpCgpnZ3Bsb3QoZGF0YT1BcmNoLGFlcyh4PUNsYXNzTmV3KSkrZ2VvbV9iYXIoZmlsbD0ibGlnaHQgYmx1ZSIpKwogIGdndGl0bGUoIlJ1bmVzdG9uZSBUeXBvbG9neSBhY3Jvc3MgZGlmZmVyZW50IFRpbWUgUGVyaW9kcyBpbiBTd2VkZW4iKSsKICBsYWJzKHg9IlRpbWUgUGVyaW9kcyIseT0iTnVtYmVyIG9mIFJ1bmVzdG9uZXMiKSArIAogIHRoZW1lX2NsZWFuKCkKCmBgYAoKCgojIyBJbXBvcnRpbmcgZGF0YQoKYGBge3IgZGF0YSBzdW1tYXJpZXN9CnJ1bmVfbWFzdCA8LSByZWFkX3hsc3goIlVwcHNhbGFfdHJpYWwueGxzeCIpCmFzLmRhdGEuZnJhbWUocnVuZV9tYXN0KQoKcnVuZWRhdGEgPC0gcmVhZF94bHN4KCIxR290bGFuZGNsZWFuLnhsc3giKQphcy5kYXRhLmZyYW1lKHJ1bmVkYXRhKSAKYGBgCgojIyMgU3VtbWFyeSBvZiBkYXRhIHNldHMKCmBgYHtyIERhdGEgU3VtbWFyeX0Kc3VtbWFyeShydW5lX21hc3QpCgpzdW1tYXJ5KHJ1bmVkYXRhKQpgYGAKCiMjIyBEYXRhIENsZWFuaW5nCmBgYHtyIERhdGEgQ2xlYW5pbmd9CnJ1bmVfbWFzdCA9IG11dGF0ZShydW5lX21hc3QsY2xhc3NpZiA9IGNhc2Vfd2hlbigKICBncmVwbCgnUkFLJyxDbGFzc2lmaWNhdGlvbil+J1JBSycsCiAgZ3JlcGwoJ0ZwJyxDbGFzc2lmaWNhdGlvbil+J0ZwJywKICBncmVwbCgnUHIxJyxDbGFzc2lmaWNhdGlvbil+J1ByMScsCiAgZ3JlcGwoJ1ByMicsQ2xhc3NpZmljYXRpb24pfidQcjInLAogIGdyZXBsKCdQcjMnLENsYXNzaWZpY2F0aW9uKX4nUHIzJywKICBncmVwbCgnUHI0JyxDbGFzc2lmaWNhdGlvbil+J1ByNCcsCiAgZ3JlcGwoJ1ByNScsQ2xhc3NpZmljYXRpb24pfidQcjUnLAogIFRSVUV+ICdOQScpKQoKZGF0YSA9IG11dGF0ZShydW5lZGF0YSxDbGFzc2lmID0gY2FzZV93aGVuKAogIGdyZXBsKCdSQUsnLENsYXNzaWYpfidSQUsnLAogIGdyZXBsKCdGcCcsQ2xhc3NpZil+J0ZwJywKICBncmVwbCgnUHIxJyxDbGFzc2lmKX4nUHIxJywKICBncmVwbCgnUHIyJyxDbGFzc2lmKX4nUHIyJywKICBncmVwbCgnUHIzJyxDbGFzc2lmKX4nUHIzJywKICBncmVwbCgnUHI0JyxDbGFzc2lmKX4nUHI0JywKICBncmVwbCgnUHI1JyxDbGFzc2lmKX4nUHI1JywKICBUUlVFfiAnTkEnKSkKCnJ1bmVkYXRhJENsYXNzaWYgPC0gZmFjdG9yKHJ1bmVkYXRhJENsYXNzaWYsIGxldmVscyA9IGMoIlJBSyIsIkZwIiwiUHIxIiwiUHIyIiwiUHIzIiwiUHI0IiwiUHI1IiwiTkEiKSwgb3JkZXJlZCA9IFRSVUUpCgpydW5lX21hc3QkY2xhc3NpZiA8LSBmYWN0b3IocnVuZV9tYXN0JGNsYXNzaWYsIGxldmVscyA9IGMoIlJBSyIsIkZwIiwiUHIxIiwiUHIyIiwiUHIzIiwiUHI0IiwiUHI1IiwiTkEiKSwgb3JkZXJlZCA9IFRSVUUpCmBgYAoKCiMjIFVwcHNhbGEgY291bnR5IHsudGFic2V0IC50YWJzZXQtZmFkZX0KCiMjIyBNYXBzIHstfQoKYGBge3IgVXBwc2FsYSwgd2FybmluZz1GQUxTRSwgdGlkeT1UUlVFfQpDbGFzcyA8LSBydW5lX21hc3QkY2xhc3NpZgpDcm9zc2VzIDwtIGZhY3RvcihydW5lX21hc3QkQ3Jvc3MsIGxldmVscyA9IGMoMDoxKSkKdXBwc2FsYV9tYXAgPC0gZ2V0X3N0YW1lbm1hcChiYm94ID1jKDE2Ljk3OTQsNTkuNjc4OCwxOC41NzUxLDYwLjEzODEpLCBtYXB0eXBlPSJ0b25lci1saXRlIiwKICB6b29tPTExKQoKZ2dtYXAodXBwc2FsYV9tYXApKwogIGdlb21fcG9pbnQoCiAgZGF0YSA9IHJ1bmVfbWFzdCwgCiAgYWVzKHg9TG9uZ2l0dWRlLCB5PUxhdGl0dWRlLCBjb2xvcj1DbGFzcywgc2hhcGU9Q3Jvc3Nlcyksc2l6ZT0yLjUsIGFscGhhPTAuNCkrCiAgdGhlbWVfbWFwKCkrdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9IkNsYXNzaWZpY2F0aW9uIikpKwogIGdndGl0bGUoIkdlb2dyYXBoaWNhbCBkaXN0cmlidXRpb24gb2YgUnVuZXN0b25lcyBpbiB0aGUgVXBwc2FsYSBDb3VudHkiKQoKZ2dtYXAodXBwc2FsYV9tYXApKwogIGdlb21fcG9pbnQoCiAgZGF0YSA9IHJ1bmVfbWFzdCwgCiAgYWVzKHg9TG9uZ2l0dWRlLCB5PUxhdGl0dWRlLCBjb2w9Q3Jvc3Nlcyksc2l6ZT0yLCBhbHBoYT0wLjQpKwogIHRoZW1lX21hcCgpKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikrCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJDbGFzc2lmaWNhdGlvbiIpKSsKICBnZ3RpdGxlKCJHZW9ncmFwaGljYWwgZGlzdHJpYnV0aW9uIG9mIFJ1bmVzdG9uZXMgaW4gdGhlIFVwcHNhbGEgQ291bnR5IikrCiAgZmFjZXRfd3JhcCh2YXJzKGNsYXNzaWYpKSsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz13ZXNfcGFsZXR0ZShuPTMsIG5hbWU9IkJvdHRsZVJvY2tldDEiKSkKCmBgYAoKIyMjIE51bWJlciBvZiBDcm9zc2VzIG92ZXIgdGltZSB7LX0KCmBgYHtyIE51bWJlciBvZiBjcm9zc2VzIFVwcHNhbGEsIGVycm9yPUZBTFNFfQp1cHBzYWxhX2Nyb3NzIDwtIGdncGxvdChkYXRhID0gcnVuZV9tYXN0LCBhZXMoeCA9IENsYXNzKSkrCiAgZ2VvbV9iYXIoYWVzKGZpbGw9Q3Jvc3NlcyksIHBvc2l0aW9uID0gImRvZGdlIikrCiAgZ2d0aXRsZSgiUHJvcG9ydGlvbiBvZiBDcm9zc2VzIGFjcm9zcyBUaW1lIGluIFVwcHNhbGEiKSsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKyAKICB0aGVtZV9idygpCiAgCmdncGxvdGx5KHVwcHNhbGFfY3Jvc3MpCgpgYGAKCgoKIyMgR290bGFuZCBDb3VudHkgey50YWJzZXQgLnRhYnNldC1mYWRlfQoKIyMjIE1hcHMgey19CgpgYGB7ciBHb3RsYW5kLCB3YXJuaW5nPUZBTFNFLCB0aWR5PVRSVUV9CkNsYXNzZXMgPC0gcnVuZWRhdGEkQ2xhc3NpZgpnb3RsYW5kX21hcCA8LSBnZXRfc3RhbWVubWFwKAogIGJib3ggPSBjKGxlZnQgPSAxNy41LCBib3R0b20gPSA1Ny4wLCByaWdodCA9IDE5LjgsIHRvcCA9IDU3LjkpLAogIG1hcHR5cGUgPSAidG9uZXItbGl0ZSIsCiAgem9vbSA9IDkKKQpnZ21hcChnb3RsYW5kX21hcCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHJ1bmVkYXRhLAogICAgICAgICAgICAgYWVzKHggPSBMb25nLCB5ID0gTGF0LGNvbCA9IENsYXNzaWYpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiT3ZlcmFsbCBEaXN0cmlidXRpb24gb2YgUnVuZXN0b25lcyBpbiB0aGUgR290bGFuZCBDb3VudHkiKSArCiAgdGhlbWVfbWFwKCkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCmdnbWFwKGdvdGxhbmRfbWFwKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcnVuZWRhdGEsCiAgICAgICAgICAgICBhZXMoeCA9IExvbmcsIHkgPSBMYXQsIGZpbGw9Q3Jvc3NlcyksYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICBzaXplID0gMC45LCBjb2wgPSAicmVkIikgKyBmYWNldF93cmFwKHZhcnMoQ2xhc3NpZikpKwogZ2d0aXRsZSgiR2VvZ3JhcGhpY2FsIERpc3RyaWJ1dGlvbiBvZiBSdW5lc3RvbmVzIGluIHRoZSBHb3RsYW5kIENvdW50eSIpICsKICB0aGVtZV9tYXAoKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSAKCgpgYGAKCgojIyMgTnVtYmVyIG9mIGNyb3NzZXMgb3ZlciB0aW1lIHstfQoKYGBge3IgTnVtYmVyIG9mIGNyb3NzZXMgR290bGFuZH0KQ3Jvc3Nlcy5Hb3RsYW5kIDwtIHJ1bmVkYXRhJENyb3NzZXMKZ290bGFuZF9jcm9zcyA8LSBnZ3Bsb3QoZGF0YSA9IHJ1bmVkYXRhLCBhZXMoeCA9IENsYXNzZXMpKStnZW9tX2JhcihhZXMoZmlsbD1Dcm9zc2VzLkdvdGxhbmQpKSsgCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSsKICBnZ3RpdGxlKCJQcm9wb3J0aW9uIG9mIENyb3NzZXMgYWNyb3NzIFRpbWUgaW4gR290bGFuZCIpKyB0aGVtZV9idygpCgoKZ2dwbG90bHkoZ290bGFuZF9jcm9zcykKCgpgYGAKCgoKIyBBY2tub3dsZWRnZW1lbnRzCgpSb2xlICAgICAgICAgICAgfCBDb29yZGluYXRvciAgICAgICAgICAgICAgfCBTdXBwb3J0Ci0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpQcmVzZW50YXRpb24gICAgfCBBcmllbCwgSmFjcXVpIChwcmVzZW50ZXIpfCBMdWFuYQpDb2RpbmcgICAgICAgICAgfCBTaHJhZGhhICAgICAgICAgICAgICAgICAgfCBSdQpTY2hlZHVsaW5nICAgICAgfCBMdWFuYSAgICAgICAgICAgICAgICAgICAgfApSZXNlYXJjaCAgICAgICAgfCBKZW5uaWZlciAgICAgICAgICAgICAgICAgfCBBcmllbCwgTHVhbmEgKGVkaXRvcnMpCgoKKioqCgoKKk1lZXRpbmdzKgoKRGF0ZSwgdGltZSAgICAgICAgICAgICAgfCBQcmVzZW50ZWUocykgfCAgRGlzY3Vzc2lvbiBwb2ludHMgICAgICAgICAgICAgCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KOC8zICgxMWFtLTEycG0pICAgICAgICAgfCAgICBBbGwgICAgICAgfFBvc3NpYmxlIHJlc2VhcmNoIHF1ZXN0aW9uczsgRmluYWxpc2Ugcm9sZXMKMTUvMyAoMTFhbS0xMnBtKSAgICAgICAgfCAgICBBbGwgICAgICAgfEZpbmFsaXNlIHJlc2VhcmNoIHF1ZXN0aW9uCjIyLzMgKDExYW0tMTJwbSkgICAgICAgIHwgICAgQWxsICAgICAgIHxDb25kdWN0IGRvbWFpbiByZXNlYXJjaCBhbmQgY29uc29saWRhdGUgZmluZGluZ3Mgd2l0aCBncm91cCBtZW1iZXJzCjI5LzMgKDExYW0tMTJwbSkgICAgICAgIHwgICAgQWxsICAgICAgIHxEaXNjdXNzIGFwcHJvYWNoIG9mIHJlc2VhcmNoIHF1ZXN0aW9uOyBCZWdpbiByZXBvcnQgZHJhZnQ7IEJlZ2luIGNvZGluZyBmb3IgZ3JhcGhpY2FsIHN1bW1hcmllcwo1LzQgKDExYW0tMTJwbSkgICAgICAgICB8ICAgIEFsbCAgICAgICB8RmluYWxpc2UgZ3JhcGhpY2FsIHN1bW1hcmllczsgRGVyaXZlIHRyZW5kcyBmcm9tIGdyYXBoaWNhbCBzdW1tYXJpZXMKMTIvNCAoMTFhbS0xMnBtKSAgICAgICAgfCAgICBBbGwgICAgICAgfEZpbG0gcHJlc2VudGF0aW9uOyBGaW5hbGlzZSByZXBvcnQgCgogCiAgICAgICAgICAgICAgICAgICAgICAgICAgCgojIEFydGljbGVzIGZvciBmdXJ0aGVyIHJlYWRpbmcKCipLbnV0c29uLCBTLiBBLiAoMjAxNikuIEJyaWRnZXMgdG8gRXRlcm5pdHk6IEEgUmUtRXhhbWluYXRpb24gb2YgdGhlIEFkb3B0aW9uIG9mIENocmlzdGlhbml0eSBpbiBWaWtpbmctQWdlIFN3ZWRlbi4gVmlraW5nIGFuZCBNZWRpZXZhbCBTY2FuZGluYXZpYSwgMTIsIDg34oCTMTAyLiBodHRwczovL3d3dy5qc3Rvci5vcmcvc3RhYmxlLzQ4NTAxNzk4KgoKS251c3RvbiBhc3NlcnRzIHRoYXQgQ2hyaXN0aWFuaXR5IHdhcyBhY3RpdmVseSB1cHRha2VuIGJ5IHRoZSBWaWtpbmdzLCBwYXJ0aWN1bGFybHkgaW4gd2VsbC1jb25uZWN0ZWQgbXVuaWNpcGFsaXRpZXMgd2hpY2ggYmVuZWZpdGVkIGZyb20gYWNjZXNzIHRvIGZvcmVpZ24gaW5mbHVlbmNlcyB2aWEgdHJhZGUgaW50ZXJhY3Rpb25zLgoKKlRob2VtaW5nLCBBLiAoMjAxNikuIERlYWxpbmcgd2l0aCBEYXRhOiBOYcOvdmUgQmF5ZXNpYW4gQ2xhc3NpZmljYXRpb24gYW5kIGEgQ2FzZSBTdHVkeSBmcm9tIFZpa2luZyBBZ2UgU3dlZGVuLiBJbnRlcm5hdGlvbmFsIEpvdXJuYWwgb2YgU3R1ZGVudCBSZXNlYXJjaCBpbiBBcmNoYWVvbG9neSwgMSgxKSwgMTkzLTIwNC4gaHR0cHM6Ly93d3cuYWNhZGVtaWEuZWR1LzIxNDMxOTIyL0RlYWxpbmdfd2l0aF9EYXRhX05hJUMzJUFGdmVfQmF5ZXNpYW5fQ2xhc3NpZmljYXRpb25fYW5kX2FfY2FzZV9zdHVkeV9mcm9tX1Zpa2luZ19BZ2VfU3dlZGVuKgoKRW5jb3VudGVyaW5nIHNpbWlsYXIgbGltaXRhdGlvbnMgaW4gdGhlIGRhdGEgdG8gdGhpcyByZXBvcnQsIFRob2VtaW5nIGRldGVybWluZWQgdGhhdCB0aGUgQmF5ZXNpYW4gY2xhc3NpZmllciB3YXMgbGltaXRlZCwgb25seSBwcm92aWRpbmcgYnJvYWRlciBjYXRlZ29yaXNhdGlvbnMgaW4gZmVhdHVyZSBjb21iaW5hdGlvbnMgYW5kIGRpZmZlcmVuY2VzLiAKCgoKIyBSZWZlcmVuY2VzCgpUdXRvcmlhbCBmb3IgY3JlYXRpbmcgbWFwczogKmh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9Mms4Ty1ZX3VpUlUqCiAKQ29udmVyc2lvbiBvZiBjb29yZGluYXRlczogKmh0dHBzOi8vY29vcmRpbmF0ZXMtY29udmVydGVyLmNvbS9lbi9kZWNpbWFsLzUxLjAwMDAwMCwxMC4wMDAwMDA/a2FydGU9T3BlblN0cmVldE1hcCZ6b29tPTgqCiAKRGF0YSBDbGVhbmluZzogKkZyZXlhIGFuZCBTZWFuIChUdWVzZGF5IExhYiBDQykqCg==